
#if defined(__GNUG__) && !defined(__APPLE__)
#pragma implementation "dragscroll.h"
#endif


#include <sdk.h>
#ifndef CB_PRECOMP
#include <wx/app.h>
#include <wx/intl.h>
#include <wx/listctrl.h>
#include "configmanager.h"
#include "manager.h"
#include "personalitymanager.h"
#include "sdk_events.h"
#endif

#include <wx/fileconf.h>
#include <wx/html/htmlwin.h>
#include <wx/tokenzr.h>
#include "cbstyledtextctrl.h"
#include "snippetsconfig.h"
#include "scbeditor.h"
#include "seditormanager.h"
#include "dragscroll.h"
#include "dragscrollcfg.h"
#include "version.h"
#include "dragscrollevent.h"
#include "logmanager.h"
#include "loggers.h"
#include "projectmanager.h"


class dsTextCtrlLogger : public TextCtrlLogger {

    friend class cbDragScroll;
  public:
    dsTextCtrlLogger() {};
    ~dsTextCtrlLogger() {};
};


namespace {

  int ID_DLG_DONE = wxNewId();
};



BEGIN_EVENT_TABLE(cbDragScroll, cbPlugin)

  EVT_UPDATE_UI(ID_DLG_DONE, cbDragScroll::OnDoConfigRequests)

  EVT_S_DRAGSCROLL_EVENT(wxID_ANY, cbDragScroll::OnDragScrollEvent_Dispatcher)
END_EVENT_TABLE()


cbDragScroll* cbDragScroll::pDragScroll;


cbDragScroll::cbDragScroll() {
  pDragScroll = this;
  m_pMouseEventsHandler = new MouseEventsHandler();
}

cbDragScroll::~cbDragScroll() {
  delete m_pMouseEventsHandler;
  m_pMouseEventsHandler = 0;
}

void cbDragScroll::OnAttach() {
  pMyLog = NULL;
  m_bNotebooksAttached = false;
  plugin = 0;
  m_pCB_AppWindow = Manager::Get()->GetAppWindow();
  if(not m_pMouseEventsHandler)
    m_pMouseEventsHandler = new MouseEventsHandler();
  m_UsableWindows.Add(_T("listctrl"));
  m_UsableWindows.Add(_T("textctrl"));
  m_UsableWindows.Add(_T("treectrl"));
  m_UsableWindows.Add(_T("treeAll"));
  m_UsableWindows.Add(_T("treeMembers"));
  m_UsableWindows.Add(_T("csTreeCtrl"));
  m_UsableWindows.Add(_T("sciwindow"));
  MouseDragScrollEnabled  = true;
  MouseEditorFocusEnabled = false;
  MouseFocusEnabled       = false;
  MouseDragDirection      = 0;
  MouseDragKey            = 0;
  MouseDragSensitivity    = 5;
  MouseToLineRatio        = 30;
  MouseContextDelay       = 10;
  MouseWheelZoom          = false;
  PropagateLogZoomSize    = false;
  m_MouseHtmlFontSize     = 0;
  m_ConfigFolder = ConfigManager::GetConfigFolder();
  m_DataFolder = ConfigManager::GetDataFolder();
  m_ExecuteFolder = FindAppPath(wxTheApp->argv[0], ::wxGetCwd(), wxEmptyString);
  wxString appName = wxConfigBase::Get()->GetAppName();
  if(::wxFileExists(m_ExecuteFolder + wxFILE_SEP_PATH + _T("default.conf")))
    m_ConfigFolder = m_ExecuteFolder;
  m_ConfigFolder.Replace(_T("
                            m_ExecuteFolder.Replace(_T("
                                wxString m_Personality = Manager::Get()->GetPersonalityManager()->GetPersonality();
                                if(m_Personality == wxT("default")) m_Personality = wxEmptyString;
                                LOGIT(_T("Personality is[%s]"), m_Personality.GetData());
                                wxString cfgFilenameStr = wxEmptyString;
  do {
    cfgFilenameStr = m_ExecuteFolder + wxFILE_SEP_PATH + GetConfig()->AppName + _T(".ini");
      LOGIT(_T("ExecCfgName[%s]"), cfgFilenameStr.c_str());
      if(::wxFileExists(cfgFilenameStr))
        break;
      cfgFilenameStr = m_ConfigFolder + wxFILE_SEP_PATH + GetConfig()->AppName + _T(".ini");
      cfgFilenameStr = cfgFilenameStr.Lower();
      cfgFilenameStr.Replace(wxT("codesnippets"), wxT("codeblocks"), false);
      LOGIT(_T("MSWCfgName 3[%s]"), cfgFilenameStr.c_str());
      if(::wxFileExists(cfgFilenameStr))
        break;
      cfgFilenameStr.Replace(wxT("codeblocks"), wxT(".codeblocks"));
      LOGIT(_T("UNXCfgName[%s]"), cfgFilenameStr.c_str());
      if(::wxFileExists(cfgFilenameStr))
        break;
      cfgFilenameStr = m_ConfigFolder + wxFILE_SEP_PATH + GetConfig()->AppName + _T(".ini");
      LOGIT(_T("DefaultCfgName[%s]"), cfgFilenameStr.c_str());
    } while(0);
    cfgFilenameStr = GetConfig()->SettingsSnippetsCfgPath;
                     m_CfgFilenameStr = cfgFilenameStr;
                     LOGIT(_T("DragScroll Config Filename:[%s]"), cfgFilenameStr.GetData());
                     wxFileConfig cfgFile(wxEmptyString,
                                          wxEmptyString,
                                          cfgFilenameStr,
                                          wxEmptyString,
                                          wxCONFIG_USE_LOCAL_FILE);
                     cfgFile.Read(_T("MouseDragScrollEnabled"),  &MouseDragScrollEnabled) ;
                     cfgFile.Read(_T("MouseEditorFocusEnabled"), &MouseEditorFocusEnabled) ;
                     cfgFile.Read(_T("MouseFocusEnabled"),       &MouseFocusEnabled) ;
                     cfgFile.Read(_T("MouseDragDirection"),      &MouseDragDirection) ;
                     cfgFile.Read(_T("MouseDragKey"),            &MouseDragKey) ;
                     cfgFile.Read(_T("MouseDragSensitivity"),    &MouseDragSensitivity) ;
                     cfgFile.Read(_T("MouseToLineRatio"),        &MouseToLineRatio) ;
                     cfgFile.Read(_T("MouseContextDelay"),       &MouseContextDelay) ;
                     cfgFile.Read(_T("MouseWheelZoom"),          &MouseWheelZoom) ;
                     cfgFile.Read(_T("PropagateLogZoomSize"),    &PropagateLogZoomSize) ;
                     cfgFile.Read(_T("MouseHtmlFontSize"),       &m_MouseHtmlFontSize, 0) ;
                     cfgFile.Read(_T("ZoomWindowIds"),           &m_ZoomWindowIds, wxEmptyString) ;
                     cfgFile.Read(_T("ZoomFontSizes"),           &m_ZoomFontSizes, wxEmptyString) ;
    if(MouseContextDelay < 10) { MouseContextDelay = 10;}
#ifdef LOGGING
LOGIT(_T("MouseDragScrollEnabled:%d"),  MouseDragScrollEnabled) ;
LOGIT(_T("MouseEditorFocusEnabled:%d"), MouseEditorFocusEnabled) ;
LOGIT(_T("MouseFocusEnabled:%d"),       MouseFocusEnabled) ;
LOGIT(_T("MouseDragDirection:%d"),      MouseDragDirection) ;
LOGIT(_T("MouseDragKey:%d"),            MouseDragKey) ;
LOGIT(_T("MouseDragSensitivity:%d"),    MouseDragSensitivity) ;
LOGIT(_T("MouseToLineRatio:%d"),        MouseToLineRatio) ;
LOGIT(_T("MouseContextDelay:%d"),       MouseContextDelay) ;
LOGIT(_T("MouseWheelZoom:%d"),          MouseWheelZoom) ;
LOGIT(_T("PropagateLogZoomSize:%d"),    PropagateLogZoomSize) ;
LOGIT(_T("MouseHtmlFontSize:%d"),       m_MouseHtmlFontSize) ;
LOGIT(_T("ZoomWindowIds:[%s]"),         m_ZoomWindowIds.c_str()) ;
LOGIT(_T("ZoomFontSizes:[%s]"),         m_ZoomFontSizes.c_str()) ;
#endif
GetZoomWindowsArraysFrom(m_ZoomWindowIds, m_ZoomFontSizes);
Connect(wxEVT_CREATE,
        (wxObjectEventFunction)(wxEventFunction)
        (wxCommandEventFunction) &cbDragScroll::OnWindowOpen);
Connect(wxEVT_DESTROY,
        (wxObjectEventFunction)(wxEventFunction)
        (wxCommandEventFunction) &cbDragScroll::OnWindowClose);
plugin = (PluginInfo*)(Manager::Get()->GetPluginManager()->GetPluginInfo(this));
if(plugin) {
  plugin->version = VERSION;
} else {
}
return ;
}

void cbDragScroll::OnRelease(bool) {
  DetachAll();
}

cbConfigurationPanel* cbDragScroll::GetConfigurationPanel(wxWindow* parent) {
  if(!IsAttached())
    return 0;
  cbDragScrollCfg* pDlg = new cbDragScrollCfg(parent, this);
  pDlg->SetMouseDragScrollEnabled(MouseDragScrollEnabled);
  pDlg->SetMouseEditorFocusEnabled(MouseEditorFocusEnabled);
  pDlg->SetMouseFocusEnabled(MouseFocusEnabled);
  pDlg->SetMouseDragDirection(MouseDragDirection);
  pDlg->SetMouseDragKey(MouseDragKey);
  pDlg->SetMouseDragSensitivity(MouseDragSensitivity);
  pDlg->SetMouseToLineRatio(MouseToLineRatio);
  pDlg->SetMouseContextDelay(MouseContextDelay);
  pDlg->SetMouseWheelZoom(MouseWheelZoom);
  pDlg->SetPropagateLogZoomSize(PropagateLogZoomSize);
  return pDlg;
}

void cbDragScroll::CenterChildOnParent(wxWindow* parent, wxWindow* child) {
  int displayX;
  int displayY;
  ::wxDisplaySize(&displayX, &displayY);
  int childx = 1, childy = 1;
  int childsizex, childsizey;
  parent->GetScreenPosition(&childx, &childy);
  child->GetSize(&childsizex, &childsizey);
  if((childx + childsizex) > displayX)
    childx = displayX - childsizex;
  if((childy + childsizey) > displayY)
    childy = displayY - childsizey;
  if(childx < 1)
    childx = 1;
  if(childy < 1)
    childy = 1;
  child->Move(childx, childy);
  return;
}

void cbDragScroll::OnDialogDone(cbDragScrollCfg* pDlg) {
  MouseDragScrollEnabled  = pDlg->GetMouseDragScrollEnabled();
  MouseEditorFocusEnabled = pDlg->GetMouseEditorFocusEnabled();
  MouseFocusEnabled       = pDlg->GetMouseFocusEnabled();
  MouseDragDirection      = pDlg->GetMouseDragDirection();
  MouseDragKey            = pDlg->GetMouseDragKey();
  MouseDragSensitivity    = pDlg->GetMouseDragSensitivity();
  MouseToLineRatio        = pDlg->GetMouseToLineRatio();
  MouseContextDelay       = pDlg->GetMouseContextDelay();
  MouseWheelZoom          = pDlg->GetMouseWheelZoom();
  PropagateLogZoomSize    = pDlg->IsLogZoomSizePropagated() and MouseWheelZoom;
  #ifdef LOGGING
  LOGIT(_T("MouseDragScrollEnabled:%d"),  MouseDragScrollEnabled);
  LOGIT(_T("MouseEditorFocusEnabled:%d"), MouseEditorFocusEnabled);
  LOGIT(_T("MouseFocusEnabled:%d"),       MouseFocusEnabled);
  LOGIT(_T("MouseDragDirection:%d"),      MouseDragDirection);
  LOGIT(_T("MouseDragKey:%d"),            MouseDragKey);
  LOGIT(_T("MouseDragSensitivity:%d"),    MouseDragSensitivity);
  LOGIT(_T("MouseToLineRatio:%d"),        MouseToLineRatio);
  LOGIT(_T("MouseContextDelay:%d"),       MouseContextDelay);
  LOGIT(_T("MouseMouseWheelZoom:%d"),     MouseWheelZoom);
  LOGIT(_T("PropagateLogZoomSize:%d"),    PropagateLogZoomSize);
  LOGIT(_T("-----------------------------"));
  #endif
  wxUpdateUIEvent eventdone(ID_DLG_DONE);
  eventdone.SetEventObject(m_pCB_AppWindow);
  m_pCB_AppWindow->GetEventHandler()->AddPendingEvent(eventdone);
}

void cbDragScroll::OnDoConfigRequests(wxUpdateUIEvent&) {
  LOGIT(_T("OnDoConfigRequest event"));
  if(GetMouseDragScrollEnabled()) {
    if(not m_bNotebooksAttached) {
      AttachRecursively(m_pCB_AppWindow);
      m_bNotebooksAttached = true;
    }
  } else {
    DetachAll();
    m_bNotebooksAttached = false;
  }
  UpdateConfigFile();
}

void cbDragScroll::UpdateConfigFile() {
  #if defined(LOGGING)
  LOGIT(_T("UpdateConfigFile"));
  #endif
  wxFileConfig cfgFile(wxEmptyString,
                       wxEmptyString,
                       m_CfgFilenameStr,
                       wxEmptyString,
                       wxCONFIG_USE_LOCAL_FILE);
  cfgFile.Write(_T("MouseDragScrollEnabled"),  MouseDragScrollEnabled) ;
  cfgFile.Write(_T("MouseEditorFocusEnabled"), MouseEditorFocusEnabled) ;
  cfgFile.Write(_T("MouseFocusEnabled"),       MouseFocusEnabled) ;
  cfgFile.Write(_T("MouseDragDirection"),      MouseDragDirection) ;
  cfgFile.Write(_T("MouseDragKey"),            MouseDragKey) ;
  cfgFile.Write(_T("MouseDragSensitivity"),    MouseDragSensitivity) ;
  cfgFile.Write(_T("MouseToLineRatio"),        MouseToLineRatio) ;
  cfgFile.Write(_T("MouseContextDelay"),       MouseContextDelay) ;
  cfgFile.Write(_T("MouseWheelZoom"),          MouseWheelZoom) ;
  cfgFile.Write(_T("PropagateLogZoomSize"),    PropagateLogZoomSize) ;
  cfgFile.Write(_T("MouseHtmlFontSize"),       m_MouseHtmlFontSize) ;
  if(not m_ZoomWindowIds.IsEmpty()) {
    cfgFile.Write(_T("ZoomWindowIds"),       m_ZoomWindowIds) ;
    cfgFile.Write(_T("ZoomFontSizes"),       m_ZoomFontSizes) ;
  }
  cfgFile.Flush();
  #ifdef LOGGING
  LOGIT(_T("DragScroll:Writing config file[%s]"), m_CfgFilenameStr.c_str());
  LOGIT(_T("MouseDragScrollEnabled:%d"),  MouseDragScrollEnabled) ;
  LOGIT(_T("MouseEditorFocusEnabled:%d"), MouseEditorFocusEnabled) ;
  LOGIT(_T("MouseFocusEnabled:%d"),       MouseFocusEnabled) ;
  LOGIT(_T("MouseDragDirection:%d"),      MouseDragDirection) ;
  LOGIT(_T("MouseDragKey:%d"),            MouseDragKey) ;
  LOGIT(_T("MouseDragSensitivity:%d"),    MouseDragSensitivity) ;
  LOGIT(_T("MouseToLineRatio:%d"),        MouseToLineRatio) ;
  LOGIT(_T("MouseContextDelay:%d"),       MouseContextDelay) ;
  LOGIT(_T("MouseWheelZoom"),             MouseWheelZoom) ;
  LOGIT(_T("PropagateLogZoomSize"),       PropagateLogZoomSize) ;
  LOGIT(_T("MouseHtmlFontSize"),          m_MouseHtmlFontSize) ;
  #endif
}
int cbDragScroll::GetZoomWindowsArraysFrom(wxString zoomWindowIds, wxString zoomFontSizes) {
  wxStringTokenizer ids(zoomWindowIds, wxT(","));
  wxStringTokenizer sizes(zoomFontSizes, wxT(","));
  while(ids.HasMoreTokens()  && sizes.HasMoreTokens()) {
    long winId ;
    long size;
    ids.GetNextToken().ToLong(&winId);
    sizes.GetNextToken().ToLong(&size);
    m_ZoomWindowIdsAry.Add(winId);
    m_ZoomFontSizesAry.Add(size);
  }
  return m_ZoomWindowIdsAry.GetCount();
}

void cbDragScroll::OnDragScrollEvent_Dispatcher(wxCommandEvent& event) {
  if(not IsAttached())
    return;
  switch(event.GetId()) {
    case idDragScrollAddWindow: {
      if(not GetMouseDragScrollEnabled())
        return;
      OnDragScrollEventAddWindow(event);
      break;
    }
    case idDragScrollRemoveWindow: {
      OnDragScrollEventRemoveWindow(event);
      break;
    }
    case idDragScrollRescan: {
      if(not GetMouseDragScrollEnabled())
        return;
      OnDragScrollEventRescan(event);
      break;
    }
    case idDragScrollReadConfig: {
      OnDragScrollEvent_RereadConfig(event);
      break;
    }
    case idDragScrollInvokeConfig: {
      OnDragScrollEvent_InvokeConfig(event);
      break;
    }
    default:
      break;
  }
}

void cbDragScroll::OnDragScrollEventAddWindow(wxCommandEvent& event) {
  wxWindow* pWin = (wxWindow*)event.GetEventObject();
  wxString winName = event.GetString();
  if((not winName.IsEmpty()) && (wxNOT_FOUND == m_UsableWindows.Index(winName)))
    m_UsableWindows.Add(winName);
  Attach(pWin);
  event.Skip();
  #if defined(LOGGING)
  int eventID = event.GetId();
  LOGIT(_T("cbDragScroll::OnDragScrollEvent AddWindow evtID[%d]@[%p][%d][%s]"), eventID, pWin, pWin->GetId(), pWin->GetName().c_str());
  #endif
}

void cbDragScroll::OnDragScrollEventRemoveWindow(wxCommandEvent& event) {
  wxWindow* pWin = (wxWindow*)event.GetEventObject();
  Detach(pWin);
  event.Skip();
  #if defined(LOGGING)
  int windowID = event.GetId();
  LOGIT(_T("cbDragScroll::OnDragScrollEvent RemoveWindow[%d][%p][%s]"), windowID, pWin, pWin->GetName().c_str());
  #endif
}

void cbDragScroll::OnDragScrollEventRescan(wxCommandEvent& event) {
  CleanUpWindowPointerArray();
  wxWindow* pWin = (wxWindow*)event.GetEventObject();
  wxString winName = event.GetString();
  if((not winName.IsEmpty()) && (wxNOT_FOUND == m_UsableWindows.Index(winName)))
    m_UsableWindows.Add(winName);
  AttachRecursively(pWin);
  event.Skip();
  #if defined(LOGGING)
  LOGIT(_T("cbDragScroll::OnDragScrollEvent Rescan[%p][%s]"), pWin, pWin->GetName().c_str());
  #endif
}

void cbDragScroll::OnDragScrollEvent_RereadConfig(wxCommandEvent&) {
  #if defined(LOGGING)
  LOGIT(_T("CodeSnippets:DragScroll RereadConfig"));
  #endif
  wxString cfgFilenameStr = GetConfig()->SettingsSnippetsCfgPath;
  m_CfgFilenameStr = cfgFilenameStr;
  LOGIT(_T("DragScroll Config Filename:[%s]"), cfgFilenameStr.GetData());
  wxFileConfig cfgFile(wxEmptyString,
                       wxEmptyString,
                       cfgFilenameStr,
                       wxEmptyString,
                       wxCONFIG_USE_LOCAL_FILE);
  cfgFile.Read(_T("MouseDragScrollEnabled"),  &MouseDragScrollEnabled) ;
  cfgFile.Read(_T("MouseEditorFocusEnabled"), &MouseEditorFocusEnabled) ;
  cfgFile.Read(_T("MouseFocusEnabled"),       &MouseFocusEnabled) ;
  cfgFile.Read(_T("MouseDragDirection"),      &MouseDragDirection) ;
  cfgFile.Read(_T("MouseDragKey"),            &MouseDragKey) ;
  cfgFile.Read(_T("MouseDragSensitivity"),    &MouseDragSensitivity) ;
  cfgFile.Read(_T("MouseToLineRatio"),        &MouseToLineRatio) ;
  cfgFile.Read(_T("MouseContextDelay"),       &MouseContextDelay) ;
  cfgFile.Read(_T("MouseWheelZoom"),          &MouseWheelZoom) ;
  cfgFile.Read(_T("PropagateLogZoomSize"),    &PropagateLogZoomSize) ;
  cfgFile.Read(_T("MouseHtmlFontSize"),       &m_MouseHtmlFontSize, 0) ;
  if(MouseContextDelay < 10)
    MouseContextDelay = 10;
  #ifdef LOGGING
  LOGIT(_T("MouseDragScrollEnabled:%d"),  MouseDragScrollEnabled) ;
  LOGIT(_T("MouseEditorFocusEnabled:%d"), MouseEditorFocusEnabled) ;
  LOGIT(_T("MouseFocusEnabled:%d"),       MouseFocusEnabled) ;
  LOGIT(_T("MouseDragDirection:%d"),      MouseDragDirection) ;
  LOGIT(_T("MouseDragKey:%d"),            MouseDragKey) ;
  LOGIT(_T("MouseDragSensitivity:%d"),    MouseDragSensitivity) ;
  LOGIT(_T("MouseToLineRatio:%d"),        MouseToLineRatio) ;
  LOGIT(_T("MouseContextDelay:%d"),       MouseContextDelay) ;
  LOGIT(_T("MouseWheelZoom:%d"),          MouseWheelZoom) ;
  LOGIT(_T("PropagateLogZoomSize:%d"),    PropagateLogZoomSize) ;
  LOGIT(_T("MouseHtmlFontSize:%d"),       m_MouseHtmlFontSize) ;
  #endif
}

void cbDragScroll::OnDragScrollEvent_InvokeConfig(wxCommandEvent& event) {
  wxWindow* parent = (wxWindow*)event.GetEventObject() ;
  Configure(parent);
}

void cbDragScroll::OnDragScrollTestRescan(wxCommandEvent&) {
  #if defined(LOGGING)
  LOGIT(_T("TEST RESCAN DragScrollevent"));
  #endif
}

void cbDragScroll::CleanUpWindowPointerArray() {
  unsigned int i = 0;
  while(i < m_WindowPtrs.GetCount()) {
    if(not winExists((wxWindow*)m_WindowPtrs.Item(i))) {
      m_WindowPtrs.RemoveAt(i);
      #if defined(LOGGING)
      #endif
    } else
      ++i;
  }
}

MouseEventsHandler* cbDragScroll::GetMouseEventsHandler() {
  if(not m_pMouseEventsHandler)
    m_pMouseEventsHandler = new MouseEventsHandler();
  return m_pMouseEventsHandler;
}

bool cbDragScroll::IsAttachedTo(wxWindow* p)

{
  if(wxNOT_FOUND == m_WindowPtrs.Index(p))
    return false;
  return true;
  #if defined(LOGGING)
  LOGIT(_T("IsAttachedTo previously[%p][%s]"), p, p->GetName().c_str());
  #endif
  return true;
}

void cbDragScroll::Attach(wxWindow *p) {
  if(!p || IsAttachedTo(p))
    return;
  wxString windowName = p->GetName().MakeLower();
  if(wxNOT_FOUND == m_UsableWindows.Index(windowName, false)) {
    LOGIT(wxT("csDS::Attach skipping [%s]"), p->GetName().c_str());
    return;
  }
  LOGIT(wxT("csDS::Attach - attaching to [%s] %p"), p->GetName().c_str(), p);
  m_WindowPtrs.Add(p);
  MouseEventsHandler* thisEvtHndlr = GetMouseEventsHandler();
  p->Connect(wxEVT_MIDDLE_DOWN,
             (wxObjectEventFunction)(wxEventFunction)
             (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
             NULL, thisEvtHndlr);
  p->Connect(wxEVT_MIDDLE_UP,
             (wxObjectEventFunction)(wxEventFunction)
             (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
             NULL, thisEvtHndlr);
  p->Connect(wxEVT_RIGHT_DOWN,
             (wxObjectEventFunction)(wxEventFunction)
             (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
             NULL, thisEvtHndlr);
  p->Connect(wxEVT_RIGHT_UP,
             (wxObjectEventFunction)(wxEventFunction)
             (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
             NULL, thisEvtHndlr);
  p->Connect(wxEVT_MOTION,
             (wxObjectEventFunction)(wxEventFunction)
             (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
             NULL, thisEvtHndlr);
  p->Connect(wxEVT_ENTER_WINDOW,
             (wxObjectEventFunction)(wxEventFunction)
             (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
             NULL, thisEvtHndlr);
  p->Connect(wxEVT_MOUSEWHEEL,
             (wxObjectEventFunction)(wxEventFunction)
             (wxMouseEventFunction)&cbDragScroll::OnMouseWheelEvent,
             NULL, this);
  #if defined(LOGGING)
  LOGIT(_T("csDS:Attach Window:%p Handler:%p"), p, thisEvtHndlr);
  #endif
}

void cbDragScroll::AttachRecursively(wxWindow *p) {
  if(!p)
    return;
  Attach(p);
  for(wxWindowList::compatibility_iterator node = p->GetChildren().GetFirst();
      node;
      node = node->GetNext()) {
    wxWindow *win = (wxWindow *)node->GetData();
    if(win)
      AttachRecursively(win);
  }
}

wxWindow* cbDragScroll::FindWindowRecursively(const wxWindow* parent, const wxWindow* handle) {
  if(parent) {
    if(parent == handle)
      return (wxWindow *)parent;
    for(wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
        node;
        node = node->GetNext()) {
      wxWindow *win = (wxWindow *)node->GetData();
      wxWindow *retwin = FindWindowRecursively(win, handle);
      if(retwin)
        return retwin;
    }
  }
  return NULL;
}

wxWindow* cbDragScroll::winExists(wxWindow *parent) {
  if(!parent)
    return NULL;
  for(wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
      node;
      node = node->GetNext()) {
    wxWindow* win = node->GetData();
    wxWindow* retwin = FindWindowRecursively(win, parent);
    if(retwin)
      return retwin;
  }
  return NULL;
}

void cbDragScroll::Detach(wxWindow* pWindow) {
  if((pWindow) && (m_WindowPtrs.Index(pWindow) != wxNOT_FOUND)) {
    #if defined(LOGGING)
    LOGIT(_T("csDS:Detaching %p"), pWindow);
    #endif
    m_WindowPtrs.Remove(pWindow);
    MouseEventsHandler* thisEvtHandler = GetMouseEventsHandler();
    if(not winExists(pWindow)) {
      LOGIT(_T("csDS:DetachAll window NOT found %p Handlr: %p"),
            pWindow, thisEvtHandler);
    } else {
      pWindow->Disconnect(wxEVT_MIDDLE_DOWN,
                          (wxObjectEventFunction)(wxEventFunction)
                          (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
                          NULL, thisEvtHandler);
      pWindow->Disconnect(wxEVT_MIDDLE_UP,
                          (wxObjectEventFunction)(wxEventFunction)
                          (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
                          NULL, thisEvtHandler);
      pWindow->Disconnect(wxEVT_RIGHT_DOWN,
                          (wxObjectEventFunction)(wxEventFunction)
                          (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
                          NULL, thisEvtHandler);
      pWindow->Disconnect(wxEVT_RIGHT_UP,
                          (wxObjectEventFunction)(wxEventFunction)
                          (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
                          NULL, thisEvtHandler);
      pWindow->Disconnect(wxEVT_MOTION,
                          (wxObjectEventFunction)(wxEventFunction)
                          (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
                          NULL, thisEvtHandler);
      pWindow->Disconnect(wxEVT_ENTER_WINDOW,
                          (wxObjectEventFunction)(wxEventFunction)
                          (wxMouseEventFunction)&MouseEventsHandler::OnMouseEvent,
                          NULL, thisEvtHandler);
      pWindow->Disconnect(wxEVT_MOUSEWHEEL,
                          (wxObjectEventFunction)(wxEventFunction)
                          (wxMouseEventFunction)&cbDragScroll::OnMouseWheelEvent,
                          NULL, this);
    }
    #if defined(LOGGING)
    LOGIT(_T("Detach: Editor:%p EvtHndlr: %p"), pWindow, thisEvtHandler);
    #endif
  }
}

void cbDragScroll::DetachAll() {
  LOGIT(wxT("csDS:DetachAll - detaching all [%d] targets"), m_WindowPtrs.GetCount());
  while(m_WindowPtrs.GetCount()) {
    wxWindow* pw = (wxWindow*)m_WindowPtrs.Item(0);
    Detach(pw);
  }
  m_WindowPtrs.Empty();
  m_bNotebooksAttached = false;
  return;
}
wxString cbDragScroll::FindAppPath(const wxString& argv0, const wxString& cwd, const wxString& appVariableName) {
  wxString str;
  if(!appVariableName.IsEmpty()) {
    str = wxGetenv(appVariableName);
    if(!str.IsEmpty())
      return str;
  }
  #if defined(__WXMAC__) && !defined(__DARWIN__)
  return cwd;
  #endif
  if(wxIsAbsolutePath(argv0))
    return wxPathOnly(argv0);
  else {
    wxString currentDir(cwd);
    if(currentDir.Last() != wxFILE_SEP_PATH)
      currentDir += wxFILE_SEP_PATH;
    str = currentDir + argv0;
    if(wxFileExists(str))
      return wxPathOnly(str);
  }
  wxPathList pathList;
  pathList.AddEnvList(wxT("PATH"));
  str = pathList.FindAbsoluteValidPath(argv0);
  if(!str.IsEmpty())
    return wxPathOnly(str);
  return wxEmptyString;
}


void cbDragScroll::OnAppStartupDone(CodeBlocksEvent& event) {
  #if defined(LOGGING)
  LOGIT(_T("AppStartupDone"));
  #endif
  OnAppStartupDoneInit();
  event.Skip();
  return;
}

void cbDragScroll::OnAppStartupDoneInit() {
  #if defined(LOGGING)
  LOGIT(_T("OnAppStartUpDoneInit()"));
  #endif
  if(not GetMouseDragScrollEnabled())
    return;
  {
    AttachRecursively(m_pCB_AppWindow);
    m_bNotebooksAttached = true;
  }
  if(GetMouseWheelZoom())
    for(size_t i = 0; i < m_WindowPtrs.GetCount(); ++i) {
      wxWindow* pWindow = (wxWindow*)m_WindowPtrs.Item(i);
      SetWindowZoom(pWindow);
    }
}

void cbDragScroll::SetWindowZoom(wxWindow* pWxWindow) {
  if(not GetMouseWheelZoom())
    return;
  for(size_t i = 0; i < m_WindowPtrs.GetCount(); ++i) {
    wxWindow* pWindow = (wxWindow*)m_WindowPtrs.Item(i);
    if(pWindow not_eq pWxWindow)
      continue;
    if((pWindow->GetName() not_eq  _T("SCIwindow"))
        and (pWindow->GetName() not_eq  _T("htmlWindow"))) {
      int windowId = pWindow->GetId();
      int posn;
      int fontSize = 0;
      wxFont font;
      if(wxNOT_FOUND not_eq(posn = m_ZoomWindowIdsAry.Index(windowId))) {
        fontSize = m_ZoomFontSizesAry.Item(posn);
        font = pWindow->GetFont();
        font.SetPointSize(fontSize);
        pWindow->SetFont(font);
        wxMouseEvent wheelEvt(wxEVT_MOUSEWHEEL);
        wheelEvt.SetEventObject(pWindow);
        wheelEvt.m_controlDown = true;
        wheelEvt.m_wheelRotation = 0;
        #if wxCHECK_VERSION(3, 0, 0)
        pWindow->GetEventHandler()->AddPendingEvent(wheelEvt);
        #else
        pWindow->AddPendingEvent(wheelEvt);
        #endif
        #if defined(LOGGING)
        LOGIT(_T("OnAppStartupDoneInit Issued Wheel Zoom event [%p][%d][%s]size[%d]"), pWindow, pWindow->GetId(), pWindow->GetName().c_str(), fontSize);
        #endif
      }
    }
  }
}

void cbDragScroll::OnProjectClose(CodeBlocksEvent&) {
  if(Manager::IsAppShuttingDown())
    return;
  ProjectsArray* prjary = Manager::Get()->GetProjectManager()->GetProjects();
  if(prjary->GetCount())
    return;
  sDragScrollEvent dsEvt(wxEVT_S_DRAGSCROLL_EVENT, idDragScrollRescan);
  dsEvt.SetEventObject(m_pCB_AppWindow);
  dsEvt.SetString(_T(""));
  this->AddPendingEvent(dsEvt);
  return;
}

void cbDragScroll::OnStartShutdown(CodeBlocksEvent&) {
  CleanUpWindowPointerArray();
  wxString zoomWindowIds = _T("");
  wxString zoomFontSizes = _T("");
  if(GetMouseWheelZoom()) {
    for(size_t i = 0; i < m_WindowPtrs.GetCount(); ++i) {
      #if defined(LOGGING)
      #endif
      zoomWindowIds << wxString::Format(_T("%d,"), ((wxWindow*)m_WindowPtrs.Item(i))->GetId());
      wxFont font = ((wxWindow*)m_WindowPtrs.Item(i))->GetFont();
      zoomFontSizes << wxString::Format(_T("%d,"), font.GetPointSize());
    }
    zoomWindowIds.Truncate(zoomWindowIds.Length() - 1);
    zoomFontSizes.Truncate(zoomFontSizes.Length() - 1);
    #if defined(LOGGING)
    #endif
  }
  SetZoomWindowsStrings(zoomWindowIds, zoomFontSizes);
  UpdateConfigFile();
}

void cbDragScroll::OnWindowOpen(wxEvent& event) {
  wxWindow* pWindow = (wxWindow*)(event.GetEventObject());
  if((not m_bNotebooksAttached)
      && (pWindow->GetName().Lower() == wxT("sciwindow"))) {
    #if defined(LOGGING)
    LOGIT(_T("OnWindowOpen[%s]"), pWindow->GetName().c_str());
    #endif
    OnAppStartupDoneInit();
  }
  if(m_bNotebooksAttached)
    do {
      wxWindow* pWindow = (wxWindow*)(event.GetEventObject());
      if(pWindow) {
        if((pWindow->GetName() ==  _T("SCIwindow"))
            or (pWindow->GetName() ==  _T("htmlWindow"))) {
          Detach(pWindow);
          #ifdef LOGGING
          LOGIT(_T("OnWindowOpen Attaching[%p][%d][%s]"),
                pWindow, pWindow->GetId(), pWindow->GetName().GetData());
          #endif
          Attach(pWindow);
        }
      }
    } while(0);
  event.Skip();
}

void cbDragScroll::OnWindowClose(wxEvent& event) {
  wxWindow* pWindow = (wxWindow*)(event.GetEventObject());
  if((pWindow) && (m_WindowPtrs.Index(pWindow) != wxNOT_FOUND)) {
    Detach(pWindow);
    #ifdef LOGGING
    LOGIT(_T("OnWindowClose Detached %p"), pWindow);
    #endif
  }
  event.Skip();
}

void cbDragScroll::OnMouseWheelEvent(wxMouseEvent& event) {
  cbDragScroll* pDS = cbDragScroll::pDragScroll;
  if(not pDS->GetMouseWheelZoom())
  {   event.Skip(); return; }
  wxObject* pEvtObject = event.GetEventObject();
  wxWindow* pEvtWindow = (wxWindow*)pEvtObject;
  if(event.GetEventType() ==  wxEVT_MOUSEWHEEL) {
    bool mouseCtrlKeyDown = event.ControlDown();
    if(not mouseCtrlKeyDown) {
      event.Skip();
      return;
    }
    if(pEvtWindow->GetName() == _T("SCIwindow"))
    {event.Skip(); return; }
    if(pEvtWindow->GetName() == _T("htmlWindow")) {
      if(not OnMouseWheelInHtmlWindowEvent(event))
        event.Skip();
      return;
    }
    #ifdef LOGGING
    #endif
    int nRotation = event.GetWheelRotation();
    wxFont ctrlFont = pEvtWindow->GetFont();
    if(nRotation > 0)
      ctrlFont.SetPointSize(ctrlFont.GetPointSize() - 1);
    if(nRotation < 0)
      ctrlFont.SetPointSize(ctrlFont.GetPointSize() + 1);
    pEvtWindow->SetFont(ctrlFont);
    if(pEvtWindow->IsKindOf(CLASSINFO(wxListCtrl))) {
      wxListCtrl* pListCtrl = (wxListCtrl*)pEvtWindow;
      for(int i = 0; i < pListCtrl->GetItemCount(); ++i) {
        wxFont font = pListCtrl->GetItemFont(i);
        font.SetPointSize(ctrlFont.GetPointSize());
        pListCtrl->SetItemFont(i, font);
      }
      pEvtWindow->Refresh();
      pEvtWindow->Update();
    }
    if(IsLogZoomSizePropagated()) {
      if(pEvtWindow->IsKindOf(CLASSINFO(wxListCtrl))
          or pEvtWindow->IsKindOf(CLASSINFO(wxTextCtrl)))
        if(IsLoggerControl((wxTextCtrl*)pEvtWindow)) {
          Manager::Get()->GetConfigManager(_T("message_manager"))->Write(_T("/log_font_size"), ctrlFont.GetPointSize());
          Manager::Get()->GetLogManager()->NotifyUpdate();
        }
    } else if(pEvtWindow->IsKindOf(CLASSINFO(wxListCtrl))
              or pEvtWindow->IsKindOf(CLASSINFO(wxTextCtrl))) {
      dsTextCtrlLogger* pLogger = 0;
      if((pLogger = IsLoggerControl((wxTextCtrl*)pEvtWindow))) {
        int newSize = ctrlFont.GetPointSize();
        int oldSize = Manager::Get()->GetConfigManager(_T("message_manager"))->ReadInt(_T("/log_font_size"), platform::macosx ? 10 : 8);
        Manager::Get()->GetConfigManager(_T("message_manager"))->Write(_T("/log_font_size"), newSize);
        pLogger->UpdateSettings();
        Manager::Get()->GetConfigManager(_T("message_manager"))->Write(_T("/log_font_size"), oldSize);
      }
    }
  }
}
bool cbDragScroll::OnMouseWheelInHtmlWindowEvent(wxMouseEvent& event) {
  #if defined(LOGGING)
  #endif
  wxHtmlWindow* pEvtWindow = (wxHtmlWindow*)event.GetEventObject();
  if(pEvtWindow->GetName() not_eq  _T("htmlWindow"))
    return false;
  int nRotation = event.GetWheelRotation();
  wxFont ctrlFont = pEvtWindow->GetFont();
  if(not m_MouseHtmlFontSize)
    m_MouseHtmlFontSize = ctrlFont.GetPointSize();
  if(nRotation > 0)
    ctrlFont.SetPointSize(--m_MouseHtmlFontSize);
  if(nRotation < 0)
    ctrlFont.SetPointSize(++m_MouseHtmlFontSize);
  #if defined(LOGGING)
  #endif
  int sizes[7] = {};
  for(int i = 0; i < 7; ++i)
    sizes[i] = m_MouseHtmlFontSize;
  pEvtWindow->SetFonts(wxEmptyString, wxEmptyString, &sizes[0]);
  #if defined(LOGGING)
  #endif
  return true;
}
dsTextCtrlLogger* cbDragScroll::IsLoggerControl(const wxTextCtrl* pControl) {
  return 0;
  dsTextCtrlLogger* pTextLogger;
  LogManager* pLogMgr = Manager::Get()->GetLogManager();
  int nNumLogs = 10;
  for(int i = 0; i < nNumLogs; ++i) {
    LogSlot& logSlot = pLogMgr->Slot(i);
    if(pLogMgr->FindIndex(logSlot.log) == pLogMgr->invalid_log)
      continue;
    pTextLogger = (dsTextCtrlLogger*)logSlot.GetLogger();
    if(pTextLogger)
      if(pTextLogger->control == pControl)
        return pTextLogger;
  }
  return 0;
}

BEGIN_EVENT_TABLE(MouseEventsHandler, wxEvtHandler)






END_EVENT_TABLE()

MouseEventsHandler::~MouseEventsHandler() {
  #if defined(LOGGING)
  LOGIT(_T("MouseEventsHandler dtor"));
  #endif
  return;
}

#ifdef __WXMSW__
void MouseEventsHandler::OnMouseEvent(wxMouseEvent& event) {
  if(event.GetEventType() ==  wxEVT_MOUSEWHEEL)
  { event.Skip(); return; }
  wxWindow* pTopWin = ::wxGetActiveWindow();
  if(pTopWin)
    pTopWin = ::wxGetTopLevelParent(pTopWin);
  else {
    event.Skip();
    return;
  }
  if((not pTopWin) || (not pTopWin->IsEnabled()))
  {event.Skip(); return;}
  wxObject* pEvtObject = event.GetEventObject();
  cbDragScroll* pDS = cbDragScroll::pDragScroll;
  if(pDS->GetMouseFocusEnabled()) {
    if(event.GetEventType() ==  wxEVT_ENTER_WINDOW) {
      if(pEvtObject)
        ((wxWindow*)pEvtObject)->SetFocus();
    }
  }
  wxScintilla* pStyledTextCtrl = 0;
  if(((wxWindow*)pEvtObject)->GetName() == _T("SCIwindow"))
    pStyledTextCtrl = (wxScintilla*)pEvtObject;
  if(event.GetEventType() ==  wxEVT_MOTION) {
    if(pDS->GetMouseEditorFocusEnabled() && pStyledTextCtrl)
      ((wxWindow*)pEvtObject)->SetFocus();
  }
  int scrollx;
  int scrolly;
  #if defined(LOGGING)
  #endif
  if(KeyDown(event)) {
    m_Direction = pDS->GetMouseDragDirection() ? 1 : -1 ;
    m_MouseMoveToLineMoveRatio = pDS->GetMouseToLineRatio() / 100.0;
    #ifdef LOGGING
    #endif
    m_MouseHasMoved = false;
    m_StartY = event.GetPosition().y;
    m_StartX = event.GetPosition().x;
    m_InitY = m_StartY;
    m_InitX = m_StartX;
    m_DragMode = DRAG_START;
    m_DragStartPos = event.GetPosition();
    #if defined(LOGGING)
    #endif
    if((GetUserDragKey() ==  wxMOUSE_BTN_MIDDLE) && event.MiddleIsDown())
      return;
    event.Skip();
    return;
  } else if(KeyUp(event) && (m_DragMode != DRAG_NONE)) {
    int lastmode = m_DragMode;
    m_DragMode = DRAG_NONE;
    #if defined(LOGGING)
    #endif
    if(lastmode ==  DRAG_DRAGGING)
      return;
    event.Skip();
    return;
  } else if(event.Dragging() && (m_DragMode != DRAG_NONE)) {
    if(not KeyIsDown(event)) {
      m_DragMode = DRAG_NONE;
      return;
    }
    if(! m_MouseHasMoved
        && abs(event.GetPosition().x - m_InitX) < 3
        && abs(event.GetPosition().y - m_InitY) < 3)
      return;
    if(m_DragMode == DRAG_START) {
      #if defined(LOGGING)
      #endif
      m_DragMode = DRAG_DRAGGING;
    }
    m_MouseHasMoved = true;
    int dX = event.GetPosition().x - m_StartX;
    int dY = event.GetPosition().y - m_StartY;
    m_RatioX = m_RatioY = m_MouseMoveToLineMoveRatio;
    if((abs(dX)*m_RatioX >= 1) || (abs(dY)*m_RatioY >= 1))
    { m_StartY = event.GetPosition().y; m_StartX = event.GetPosition().x;}
    int nThreshold = 1 + (100 - (pDS->GetMouseDragSensitivity() * 10));
    m_RatioX += (abs(dX) / nThreshold);
    m_RatioY += (abs(dY) / nThreshold);
    if(abs(dX) > abs(dY)) {
      scrolly = 0;
      scrollx = int(dX * m_RatioX);
    } else {
      scrollx = 0;
      scrolly = int(dY * m_RatioY);
    }
    #if defined(LOGGING)
    #endif
    if((scrollx == 0) && (scrolly == 0))
      return;
    scrollx *= m_Direction;
    scrolly *= m_Direction;
    if(pStyledTextCtrl)
      pStyledTextCtrl->LineScroll(scrollx, scrolly);
    else {
      if(scrolly)
        ((wxWindow*)pEvtObject)->ScrollLines(scrolly);
      else
        ((wxListCtrl*)pEvtObject)->ScrollList(scrollx << 2, scrolly);
    }
  }
  event.Skip();
}#endif


#if defined(__WXGTK__) || defined(__WXMAC__)
void MouseEventsHandler::OnMouseEvent(wxMouseEvent& event) {
  if(event.GetEventType() ==  wxEVT_MOUSEWHEEL)
  { event.Skip(); return; }
  wxWindow* pTopWin = ::wxGetActiveWindow();
  if(pTopWin)
    pTopWin = ::wxGetTopLevelParent(pTopWin);
  else {
    event.Skip();
    return;
  }
  if((not pTopWin) || (not pTopWin->IsEnabled()))
  {event.Skip(); return;}
  wxObject* pEvtObject = event.GetEventObject();
  cbDragScroll* pDS = cbDragScroll::pDragScroll;
  if(pDS->GetMouseFocusEnabled()) {
    if(event.GetEventType() ==  wxEVT_ENTER_WINDOW)
      if(pEvtObject)
        ((wxWindow*)pEvtObject)->SetFocus();
  }
  wxScintilla* pStyledTextCtrl = 0;
  if(((wxWindow*)pEvtObject)->GetName() == _T("SCIwindow"))
    pStyledTextCtrl = (wxScintilla*)pEvtObject;
  if(event.GetEventType() ==  wxEVT_MOTION) {
    if(pDS->GetMouseEditorFocusEnabled() && pStyledTextCtrl)
      ((wxWindow*)pEvtObject)->SetFocus();
  }
  int scrollx;
  int scrolly;
  #if defined(LOGGING)
  #endif
  if(KeyDown(event)) {
    m_Direction = pDS->GetMouseDragDirection() ? 1 : -1 ;
    m_MouseMoveToLineMoveRatio = pDS->GetMouseToLineRatio() / 100.0;
    m_MouseHasMoved = false;
    m_StartY = event.GetPosition().y;
    m_StartX = event.GetPosition().x;
    m_InitY = m_StartY;
    m_InitX = m_StartX;
    m_DragMode = DRAG_NONE;
    m_DragStartPos = event.GetPosition();
    #if defined(LOGGING)
    LOGIT(_T("Down at  X:%d Y:%d"), m_InitX, m_InitY);
    #endif
    wxPoint mouseXY = ((wxWindow*)pEvtObject)->ScreenToClient(wxGetMousePosition());
    LOGIT(_T("Down MoveTo X:%d Y:%d"), mouseXY.x, mouseXY.y);
    for(int i = 0; i < pDS->GetMouseContextDelay();) {
      ::wxMilliSleep(10);
      mouseXY = ((wxWindow*)pEvtObject)->ScreenToClient(wxGetMousePosition());
      scrollx = abs(mouseXY.x - m_InitX) ;
      scrolly = abs(mouseXY.y - m_InitY) ;
      if((scrolly > 2) || (scrollx > 2))
        break;
      i += 10;
    }
    if((GetUserDragKey() ==  wxMOUSE_BTN_MIDDLE) && event.MiddleIsDown()) {
      m_DragMode = DRAG_START;
      return;
    } else {
      #if defined(LOGGING)
      LOGIT(_T("Down delta x:%d y:%d"), scrollx, scrolly);
      #endif
      if(pStyledTextCtrl && (pEvtObject == pStyledTextCtrl)
          && ((scrolly > 2) || (scrollx > 2))) {
        m_DragMode = DRAG_START;
        return;
      } else {
        if((scrolly > 2) || (scrollx > 2)) {
          m_DragMode = DRAG_START;
          return;
        }
      }
    }
    event.Skip();
    return;
  } else if(KeyUp(event)) {
    int lastmode = m_DragMode;
    m_DragMode = DRAG_NONE;
    #if defined(LOGGING)
    LOGIT(_T("Up")) ;
    #endif
    if(lastmode ==  DRAG_DRAGGING)
      return;
    event.Skip();
    return;
  } else if((m_DragMode != DRAG_NONE) && event.Dragging()) {
    if(not KeyIsDown(event)) {
      m_DragMode = DRAG_NONE;
      return;
    }
    if(m_DragMode == DRAG_START) {
      #if defined(LOGGING)
      LOGIT(_T("Drag_Start"));
      #endif
      m_DragMode = DRAG_DRAGGING;
    }
    m_MouseHasMoved = true;
    int dX = event.GetPosition().x - m_StartX;
    int dY = event.GetPosition().y - m_StartY;
    m_RatioX = m_RatioY = m_MouseMoveToLineMoveRatio;
    if((abs(dX)*m_RatioX >= 1) || (abs(dY)*m_RatioY >= 1))
    { m_StartY = event.GetPosition().y; m_StartX = event.GetPosition().x;}
    int nThreshold = 1 + (100 - (pDS->GetMouseDragSensitivity() * 10));
    m_RatioX += (abs(dX) / nThreshold);
    m_RatioY += (abs(dY) / nThreshold);
    if(abs(dX) > abs(dY)) {
      scrolly = 0;
      scrollx = int(dX * m_RatioX);
    } else {
      scrollx = 0;
      scrolly = int(dY * m_RatioY);
    }
    #if defined(LOGGING)
    #endif
    if((scrollx == 0) && (scrolly == 0))
      return;
    scrollx *= m_Direction;
    scrolly *= m_Direction;
    if(pStyledTextCtrl)
      pStyledTextCtrl->LineScroll(scrollx, scrolly);
    else {
      if(scrolly)
        ((wxWindow*)pEvtObject)->ScrollLines(scrolly);
    }
  }
  event.Skip();
}#endif

